﻿using System;
using System.ComponentModel;
using ArtMath.Component.Point;
using ArtMath.Attribute;
using ArtMath.Data;
using ArtMath.PointCollection;
using ArtMath.Core.Helper;
using ArtMath.Resource;

namespace ArtMath.Component.Line
{
    /// <summary>
    /// 垂线段
    /// </summary>
    [Serializable]
    public class VerticalLineSegment : LineSegmentBase
    {
        StraightLineBase line;
        bool unlimit;
        public VerticalLineSegment(SketchPad pad, string name, StraightLineBase line, bool addToList = true) : base(pad, name, ToolTypeName.cxd, addToList)
        {
            StraightLine = line;
        }
        [MultilingualDisplayName("AnchorPoint")]
        public override PointBase Point1
        {
            get
            {
                return base.Point1;
            }

            set
            {
                base.Point1 = value;
            }
        }
        [MultilingualCategory("Parameter"), MultilingualDisplayName("FootPoint"), ReadOnly(true)]
        public override PointBase Point2
        {
            get
            {
                return base.Point2;
            }

            set
            {
                base.Point2 = value;
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("StraightLine"), TypeConverter(typeof(ExpandableObjectConverter))]
        public StraightLineBase StraightLine
        {
            get { return line; }
            set
            {
                line?.OutChildren_Line.Remove(this);
                line = value;
                line?.OutChildren_Line.Add(this);
            }
        }
        [Browsable(false)]
        public override AngleStringX RotateAngle
        {
            get
            {
                return base.RotateAngle;
            }

            set
            {
                base.RotateAngle = value;
            }
        }
        [Browsable(false)]
        public override RPointS RotateCenter
        {
            get
            {
                return base.RotateCenter;
            }

            set
            {
                base.RotateCenter = value;
            }
        }
        public override double NewSlope
        {
            get
            {
                return -1 / StraightLine.NewSlope;
            }
        }
        public override double NewPSlope
        {
            get
            {
                return Pad.GetVerticalLinePSlope(StraightLine.NewPSlope);
            }
        }
        public override bool PointsHaveConstraint
        {
            get { return true; }
        }
        public override int ClickTimes
        {
            get
            {
                return 1;
            }
        }
        public override void InternalPointMove(PointBase movePoint, Base sender = null)
        {
            if (movePoint == Point1)
            {
                unlimit = true;
                try
                {
                    Point2.Move(Pad.XYToPxy(Point1.NewXY.GetProjectivePoint(StraightLine.NewLocation, StraightLine.NewSlope)));
                }
                finally
                {
                    unlimit = false;
                }
            }
        }
        public override PointCollectionBase[] GetInPointMovingRange(PointBase movePoint, Base sender = null)
        {
            if (movePoint == Point2)
            {
                if (unlimit) return Universal.GenerateInstanceArray();
                return new PointCollectionBase[] { new DiscontinuityPoint(Point1.NewXY.GetProjectivePoint(StraightLine.NewLocation, StraightLine.NewSlope)) };
            }
            return base.GetInPointMovingRange(movePoint, sender);
        }
        protected override void PointMoving_AsOutChildrenLimit(PointBase movePoint)
        {
            int movcnt = CountMovablePoints();
            switch (movcnt)
            {
                case 0:
                    if (!StraightLine.NewSlope.AlmostEqual(StraightLine.Slope))
                    {
                        throw new PointMovingException(this, OfTranslator2(Resources.JoinLocalizedString("FootPoint", "CannotMove")));
                    }
                    break;
                case 1:
                case 2:
                    unlimit = Point1.TempMoveLock = true;
                    try
                    {
                        Point2.Move(Pad.XYToPxy(Point1.NewXY.GetProjectivePoint(StraightLine.NewLocation, StraightLine.NewSlope)));
                    }
                    finally
                    {
                        unlimit = Point1.TempMoveLock = false;
                    }
                    break;
            }
        }
        public override bool AllowSwitchPointType(PointBase pt)
        {
            if (pt == Point2)
            {
                return false;
            }
            return base.AllowSwitchPointType(pt);
        }
        public override void CreateComponents()
        {
            Point1 = Pad.CreatePoint(Resources.Translate("AnchorPoint"), SpareCoordinate_);
            Point2 = Pad.CreatePoint(Resources.Translate("FootPoint"), Pad.XYToPxy(Point1.ToPointD().GetProjectivePoint(StraightLine.Location, StraightLine.Slope)), false);
            base.CreateComponents();
        }
    }
}
